<template>
  <view>
    <view class="input" @click="showPopup">
      <text v-if="modelValue">{{ modelValue }}</text>
      <text v-else class="placeholder">请选择时间</text></view
    >
    <MyPopup
      class="popup"
      position="bottom"
      :show="state.show"
      @hide="hidePopup"
    >
      <view class="handle">
        <view class="cancel" @click="hidePopup">取消</view>
        <view class="confirm" @click="confirm">确定</view>
      </view>
      <picker-view
        class="picker-view"
        :value="state.initSelectedIndexs"
        @change="change"
      >
        <template v-if="date">
          <picker-view-column class="picker-view-column">
            <view
              class="item"
              v-for="(item, index) in state.date"
              :key="index"
              >{{ formatDateShow(item) }}</view
            >
          </picker-view-column>
        </template>
        <template v-if="time"
          ><picker-view-column class="picker-view-column">
            <view class="item" v-for="(item, index) in state.hours" :key="index"
              >{{ item }}时</view
            >
          </picker-view-column>
          <picker-view-column class="picker-view-column">
            <view
              class="item"
              v-for="(item, index) in state.minutes"
              :key="index"
              >{{ item }}分</view
            >
          </picker-view-column></template
        >
      </picker-view>
    </MyPopup>
  </view>
</template>

<script>
import { generateArray } from "@/utils/methods";

export default {
  props: {
    modelValue: {
      type: [String, Number],
      required: true,
    },
    startTime: {
      type: Number,
      default: Date.now() - 1000 * 3600 * 24 * 180,
    },
    endTime: {
      type: Number,
      default: Date.now(),
    },
    time: {
      type: Boolean,
      default: false,
    },
    date: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      state: {
        initSelectedIndexs: [],
        selectedIndexs: [],
        date: [],
        show: false,
        years: [],
        months: [],
        days: [],
        hours: [],
        minutes: [],
        seconds: [],
      },
    };
  },
  computed: {
    startDate() {
      const date = new Date(this.startTime);
      const year = date.getFullYear();
      const month = date.getMonth() + 1;
      const day = date.getDate();
      const hour = date.getHours();
      const mintue = date.getMinutes();
      return {
        date,
        year,
        month,
        day,
        hour,
        mintue,
      };
    },
    endDate() {
      const date = new Date(this.endTime);
      const year = date.getFullYear();
      const month = date.getMonth() + 1;
      const day = date.getDate();
      const hour = date.getHours();
      const mintue = date.getMinutes();
      return {
        date,
        year,
        month,
        day,
        hour,
        mintue,
      };
    },
    lastDateIndex() {
      return this.state.date.length - 1;
    },
    lastHourIndex() {
      return this.state.hours.length - 1;
    },
    modelValueDate() {
      let date;
      if (this.modelValue) {
        date = new Date(this.modelValue);
      } else {
        date = new Date(this.startTime);
      }
      return date;
    },
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      if (this.date) {
        const startYear = this.startDate.year;
        const endYear = this.endDate.year;
        this.state.years = generateArray(startYear, endYear, (index) =>
          index.toString()
        );
        const lastYear = this.state.years[this.state.years.length - 1];
        const startMonth = this.startDate.month;
        const startDay = this.startDate.day;
        const lastMonth = this.endDate.month;
        const lastDay = this.endDate.day;
        let monthRange = generateArray(1, 12, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
        let dayRange = generateArray(1, 31, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
        this.state.years.forEach((year, index) => {
          let sliceMonthStartIndex = 0;
          let sliceMonthEndIndex = monthRange.length;
          if (index === 0) {
            sliceMonthStartIndex = startMonth - 1;
          }
          if (year === lastYear) {
            sliceMonthEndIndex = lastMonth;
          }
          monthRange = monthRange.slice(sliceMonthStartIndex, sliceMonthEndIndex);
          monthRange.forEach((month, index) => {
            let sliceDayStartIndex = 0;
            let sliceDayEndIndex = dayRange.length;
            if (index === 0 && month === startMonth.toString()) {
              sliceDayStartIndex = startDay - 1;
            }
            if (year === lastYear && month === lastMonth.toString()) {
              sliceDayEndIndex = lastDay;
            } else {
              if (["01", "03", "05", "07", "08", "10", "12"].includes(month)) {
              } else if (["04", "06", "09", "11"].includes(month)) {
                sliceDayEndIndex = sliceDayEndIndex - 1;
              } else {
                const parseIntYear = parseInt(year);
                if (
                  parseIntYear % 400 === 0 ||
                  (parseIntYear % 4 === 0 && parseIntYear % 100 !== 0)
                ) {
                  sliceDayEndIndex = sliceDayEndIndex - 2;
                } else {
                  sliceDayEndIndex = sliceDayEndIndex - 3;
                }
              }
            }
            dayRange = dayRange.slice(sliceDayStartIndex, sliceDayEndIndex);
            dayRange.forEach((day) => {
              this.state.date.push({
                year,
                month,
                day,
              });
            });
          });
        });
      }
      if (this.time) {
        this.state.hours = generateArray(0, 23, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
        this.state.minutes = generateArray(0, 59, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
      }
    },
    initSelectorPosition() {
      if (this.modelValueDate) {
        const year = this.modelValueDate.getFullYear().toString();
        let month = (this.modelValueDate.getMonth() + 1).toString();
        let day = this.modelValueDate.getDate().toString();
        let hour = this.modelValueDate.getHours().toString();
        let minute = this.modelValueDate.getMinutes().toString();

        if (parseInt(month) < 10) month = "0" + month;
        if (parseInt(day) < 10) day = "0" + day;
        if (parseInt(hour) < 10) hour = "0" + hour;
        if (parseInt(minute) < 10) minute = "0" + minute;

        let dateIndex = 0;
        let hourIndex = 0;
        let minuteIndex = 0;
        if (
          this.modelValueDate.getTime() < this.endTime &&
          this.modelValueDate.getTime() > this.startTime
        ) {
          dateIndex = this.state.date.findIndex(
            (item) => item.year === year && item.month === month && item.day === day
          );
          hourIndex = this.state.hours.findIndex((item) => item === hour);
          minuteIndex = this.state.minutes.findIndex((item) => item === minute);
        }

        if (this.time && this.date) {
          if (dateIndex === 0) {
            this.state.hours = generateArray(this.startDate.hour, 23, (index) => {
              if (index < 10) {
                return "0" + index;
              } else {
                return index.toString();
              }
            });
            if (hourIndex === 0) {
              this.state.minutes = generateArray(this.startDate.mintue, 59, (index) => {
                if (index < 10) {
                  return "0" + index;
                } else {
                  return index.toString();
                }
              });
            }
          }
          if (dateIndex === this.lastDateIndex) {
            this.state.hours = generateArray(0, this.endDate.hour + 1, (index) => {
              if (index < 10) {
                return "0" + index;
              } else {
                return index.toString();
              }
            });
            if (hourIndex === this.lastHourIndex) {
              this.state.minutes = generateArray(0, this.endDate.mintue + 1, (index) => {
                if (index < 10) {
                  return "0" + index;
                } else {
                  return index.toString();
                }
              });
            }
          }
          this.state.initSelectedIndexs = [dateIndex, hourIndex, minuteIndex];
        } else if (this.time) {
          if (hourIndex === 0) {
            this.state.minutes = generateArray(this.startDate.mintue, 59, (index) => {
              if (index < 10) {
                return "0" + index;
              } else {
                return index.toString();
              }
            });
          }
          if (hourIndex === this.lastHourIndex) {
            this.state.minutes = generateArray(0, this.endDate.mintue + 1, (index) => {
              if (index < 10) {
                return "0" + index;
              } else {
                return index.toString();
              }
            });
          }
          this.state.initSelectedIndexs = [hourIndex, minuteIndex];
        } else if (this.date) {
          this.state.initSelectedIndexs = [dateIndex];
        }
      } else {
        this.state.initSelectedIndexs = [0, 0, 0];
      }
      this.state.selectedIndexs = this.state.initSelectedIndexs;
    },
    showPopup() {
      this.state.show = true;
      this.initSelectorPosition();
    },
    hidePopup() {
      this.state.show = false;
    },
    formatDateShow(date) {
      const { year, month, day } = date;
      const currentDate = new Date();
      let currentYear = currentDate.getFullYear().toString();
      let currentMonth = (currentDate.getMonth() + 1).toString();
      let currentDay = currentDate.getDate().toString();
      if (year === currentYear) {
        if (parseInt(currentMonth) < 10) {
          currentMonth = "0" + currentMonth;
        }
        if (month === currentMonth) {
          if (parseInt(currentDay) < 10) {
            currentDay = "0" + currentDay;
          }
          if (day === currentDay) {
            return "今日";
          }
        }
      }
      return `${parseInt(year) % 100}年${month}月${day}日`;
    },
    change(e) {
      this.state.selectedIndexs = e.detail.value;
      const value = e.detail.value;

      if (this.date && this.time) {
        let sliceHourStartIndex = 0;
        let sliceHourEndIndex = generateArray(0, 23, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        }).length;
        let sliceMinuteStartIndex = 0;
        let sliceMinuteEndIndex = generateArray(0, 59, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        }).length;
        if (value[0] === 0) {
          sliceHourStartIndex = this.startDate.hour;
          if (value[1] === 0) {
            const startMinute = this.startDate.mintue;
            sliceMinuteStartIndex = startMinute;
          }
        }
        if (value[0] === this.lastDateIndex) {
          const endHour = this.endDate.hour;
          sliceHourEndIndex = endHour + 1;

          if (value[1] === this.lastHourIndex) {
            const endMinute = this.endDate.mintue;
            sliceMinuteEndIndex = endMinute + 1;
          }
        }
        this.state.hours = generateArray(sliceHourStartIndex, sliceHourEndIndex - 1, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
        this.state.minutes = generateArray(sliceMinuteStartIndex, sliceMinuteEndIndex - 1, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
      } else if (this.time) {
        let sliceMinuteStartIndex = 0;
        let sliceMinuteEndIndex = generateArray(0, 59, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        }).length;
        if (value[0] === this.lastHourIndex) {
          const endMinute = this.endDate.mintue;
          sliceMinuteEndIndex = endMinute + 1;
        }
        this.state.minutes = generateArray(sliceMinuteStartIndex, sliceMinuteEndIndex - 1, (index) => {
          if (index < 10) {
            return "0" + index;
          } else {
            return index.toString();
          }
        });
      }
    },
    confirm() {
      let selectedDate = "";
      if (this.time && this.date) {
        const [dateIndex, hourIndex, minuteIndex] = this.state.selectedIndexs;
        const date = this.state.date[dateIndex];
        let { year, month, day } = date;
        const hour = this.state.hours[hourIndex];
        const minute = this.state.minutes[minuteIndex];

        selectedDate = `${year}-${month}-${day} ${hour}:${minute}`;
      } else if (this.time) {
        const [hourIndex, minuteIndex] = this.state.selectedIndexs;
        const hour = this.state.hours[hourIndex];
        const minute = this.state.minutes[minuteIndex];

        selectedDate = `${hour}:${minute}`;
      } else if (this.date) {
        const [dateIndex] = this.state.selectedIndexs;
        const date = this.state.date[dateIndex];
        let { year, month, day } = date;

        selectedDate = `${year}-${month}-${day}`;
      }
      this.$emit("update:modelValue", selectedDate);
      this.hidePopup